package com.mobsandgeeks.adapters;

import ohos.aafwk.ability.fraction.FractionAbility;
import ohos.agp.components.BaseItemProvider;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.Text;
import ohos.app.Context;

import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

/**
 * 一个非常简单的适配器，它向为 {@link ohos.agp.components.ListContainer} 编写的适配器添加部分。注意：该适配器假定修饰列表适配器的数据源已排序
 *
 * @param <T> T
 * @since 2021-07-02
 */
public class SimpleSectionAdapter<T> extends BaseItemProvider {
    private static final int VIEW_TYPE_SECTION_HEADER = 0;
    private static final boolean DEBUG = true;
    private static final String TAG = SimpleSectionAdapter.class.getSimpleName();
    private FractionAbility mContext;
    private InstantAdapter mListAdapter;
    private int mSectionHeaderLayoutId;
    private int mSectionTitleTextViewId;
    private Sectionizer<T> mSectionizer;
    private LinkedHashMap<String, Integer> mSections;

    /**
     * 构造
     *
     * @param fractionAbility
     * @param listAdapter
     * @param layoutSectionHeader
     * @param idSectionText
     * @param sectionizer
     * @throws IllegalArgumentException IllegalArgumentException
     */
    public SimpleSectionAdapter(FractionAbility fractionAbility, InstantAdapter listAdapter,
                                int layoutSectionHeader, int idSectionText, Sectionizer<T> sectionizer) {
        if (fractionAbility == null) {
            throw new IllegalArgumentException("context cannot be null.");
        } else if (listAdapter == null) {
            throw new IllegalArgumentException("listAdapter cannot be null.");
        } else if (sectionizer == null) {
            throw new IllegalArgumentException("sectionizer cannot be null.");
        } else if (!isTextView(fractionAbility, layoutSectionHeader, idSectionText)) {
            throw new IllegalArgumentException("sectionTitleTextViewId should be an TextView.");
        }
        this.mContext = fractionAbility;
        this.mListAdapter = listAdapter;
        this.mSectionHeaderLayoutId = layoutSectionHeader;
        this.mSectionTitleTextViewId = idSectionText;
        this.mSectionizer = sectionizer;
        this.mSections = new LinkedHashMap<String, Integer>();
        findSections();
    }

    /**
     * findSections
     */
    private void findSections() {
        int count = mListAdapter.getCount();
        int nsections = 0;
        mSections.clear();
        for (int ii = 0; ii < count; ii++) {
            String sectionName = mSectionizer.getSectionTitleForItem((T) mListAdapter.getItem(ii));

            if (!mSections.containsKey(sectionName)) {
                mSections.put(sectionName, ii + nsections);
                nsections++;
            }
        }
        if (DEBUG) {
            LogUtils.log(LogUtils.DEBUG, TAG, String.format(Locale.ROOT,"Found %d sections.", mSections.size()));
        }
    }

    @Override
    public int getCount() {
        return mListAdapter.getCount() + getSectionCount();
    }

    @Override
    public Object getItem(int position) {
        return mListAdapter.getItemId(getIndexForPosition(position));
    }

    @Override
    public long getItemId(int position) {
        return mListAdapter.getItemId(getIndexForPosition(position));
    }

    @Override
    public Component getComponent(int position, Component component, ComponentContainer componentContainer) {
        Component view = component;
        SectionHolder sectionHolder = null;
        switch (getItemComponentType(position)) {
            case VIEW_TYPE_SECTION_HEADER:
                if (view == null) {
                    view = LayoutScatter.getInstance(mContext).parse(mSectionHeaderLayoutId, null, false);
                    sectionHolder = new SectionHolder();
                    sectionHolder.titleTextView = (Text) view.findComponentById(mSectionTitleTextViewId);

                    view.setTag(sectionHolder);
                } else {
                    sectionHolder = new SectionHolder();
                    sectionHolder.titleTextView = (Text) view.findComponentById(mSectionTitleTextViewId);
                }
                break;

            default:
                view = mListAdapter.getComponent(getIndexForPosition(position),
                        component, componentContainer);
                break;
        }

        if (sectionHolder != null) {
            String sectionName = sectionTitleForPosition(position);
            sectionHolder.titleTextView.setText(sectionName);
        }

        return view;
    }

    @Override
    public void notifyDataChanged() {
        mListAdapter.notifyDataChanged();
        findSections();
        super.notifyDataChanged();
    }

    @Override
    public int getItemComponentType(int position) {
        int positionInCustomAdapter = getIndexForPosition(position);
        return mSections.values().contains(position)
                ? VIEW_TYPE_SECTION_HEADER
                : mListAdapter.getItemComponentType(positionInCustomAdapter) + 1;
    }

    @Override
    public int getComponentTypeCount() {
        return mListAdapter.getComponentTypeCount() + 1;
    }

    private boolean isTextView(Context context, int layoutId, int textViewId) {
        Component inflatedView = LayoutScatter.getInstance(context).parse(layoutId, null, false);
        Component foundView = inflatedView.findComponentById(textViewId);
        return foundView instanceof Text;
    }

    private int getSectionCount() {
        return mSections.size();
    }

    private String sectionTitleForPosition(int position) {
        String title = null;

        Set<Map.Entry<String, Integer>> entrySet = mSections.entrySet();
        for (Map.Entry<String, Integer> entry : entrySet) {
            if (entry.getValue() == position) {
                title = entry.getKey();
                break;
            }
        }
        return title;
    }

    /**
     * SectionHolder
     *
     * @since 2021-07-02
     */
    static class SectionHolder {
        private static Text titleTextView;

        public static Text getTitleTextView() {
            return titleTextView;
        }

        public static void setTitleTextView(Text titleTextView) {
            SectionHolder.titleTextView = titleTextView;
        }
    }

    /**
     * getIndexForPosition
     *
     * @param position
     * @return int
     */
    public int getIndexForPosition(int position) {
        int nsections = 0;
        Set<Map.Entry<String, Integer>> entrySet = mSections.entrySet();
        for (Map.Entry<String, Integer> entry : entrySet) {
            if (entry.getValue() < position) {
                nsections++;
            }
        }
        return position - nsections;
    }
}
